---
title: 一文读懂 ggraph 的使用
author: gaoch
date: '2019-12-04'
slug: ggraph-manual
categories:
  - ggraph
tags:
  - ggraph
---

<script src="/rmarkdown-libs/header-attrs/header-attrs.js"></script>


<p>ggraph 可用于 <strong>网络、图和树状</strong> 数据结构的可视化。它扩展了 <code>ggplot2</code> 的 geoms，facets 等功能，并且添加了对 <em>layouts</em> 语法的支持。</p>
<p>先看一个简单的例子。</p>
<pre class="r"><code>library(ggraph)</code></pre>
<pre><code>## 载入需要的程辑包：ggplot2</code></pre>
<pre class="r"><code>library(tidygraph)</code></pre>
<pre><code>## 
## 载入程辑包：&#39;tidygraph&#39;</code></pre>
<pre><code>## The following object is masked from &#39;package:stats&#39;:
## 
##     filter</code></pre>
<pre class="r"><code># Create graph of highschool friendships
graph &lt;- as_tbl_graph(highschool) %&gt;% 
    mutate(Popularity = centrality_degree(mode = &#39;in&#39;))</code></pre>
<p>这个数据（<code>highschool</code>）包含了学校成员之间的联系。第一列是一个人（from），第二列是另一个人（to），第三列是这个连接（edge）的属性。</p>
<pre class="r"><code>highschool</code></pre>
<pre><code>##    from to year
## 1     1 14 1957
## 2     1 15 1957
## 3     1 21 1957
## 4     1 54 1957
## 5     1 55 1957
## 6     2 21 1957
## 7     2 22 1957
## 8     3  9 1957
## 9     3 15 1957
## 10    4  5 1957
## 11    4 18 1957
## 12    4 19 1957
## 13    4 43 1957
## 14    5 19 1957
## 15    5 43 1957
## 16    6 13 1957
## 17    6 20 1957
## 18    6 22 1957
## 19    7 17 1957
## 20    8 14 1957
## 21    8 17 1957
## 22    9 12 1957
## 23    9 20 1957
## 24    9 21 1957
## 25    9 22 1957
## 26    9 51 1957
## 27   11 19 1957
## 28   11 50 1957
## 29   11 52 1957
## 30   11 53 1957
## 31   12 20 1957
## 32   12 21 1957
## 33   12 22 1957
##  [ reached &#39;max&#39; / getOption(&quot;max.print&quot;) -- omitted 473 rows ]</code></pre>
<p>在生成图（graph）之后，计算了节点（node）的 centrality。</p>
<pre class="r"><code>graph</code></pre>
<pre><code>## # A tbl_graph: 70 nodes and 506 edges
## #
## # A directed multigraph with 1 component
## #
## # Node Data: 70 x 2 (active)
##   name  Popularity
##   &lt;chr&gt;      &lt;dbl&gt;
## 1 1              2
## 2 2              0
## 3 3              0
## 4 4              4
## 5 5              5
## 6 6              2
## # ... with 64 more rows
## #
## # Edge Data: 506 x 3
##    from    to  year
##   &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
## 1     1    13  1957
## 2     1    14  1957
## 3     1    20  1957
## # ... with 503 more rows</code></pre>
<p>这样的一个 graph 含有 70 个节点，506 条边，是一个有向图（directed）。Node 的属性 Popularity 是刚刚上面计算的，edge 的属性是 <code>highschool</code> 数据框本来就有的。</p>
<p>使用 <code>ggraph</code> 等函数可以将这个一个图可视化。</p>
<pre class="r"><code># plot using ggraph
ggraph(graph, layout = &#39;kk&#39;) + 
    geom_edge_fan(aes(alpha = stat(index)), show.legend = FALSE) + 
    geom_node_point(aes(size = Popularity)) + 
    facet_edges(~year) + 
    theme_graph(foreground = &#39;steelblue&#39;, fg_text_colour = &#39;white&#39;)</code></pre>
<pre><code>## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): Windows字体数据
## 库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): Windows字体数据
## 库里没有这样的字体系列

## Warning in grid.Call(C_stringMetric, as.graphicsAnnot(x$label)): Windows字体数据
## 库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-5-1.png" width="672" /></p>
<p>在这里，分两年显示了学生间的亲密关系，与更多人有联系的同学受欢迎程度更大（Popularity），其节点的大小越大。</p>
<div id="核心概念" class="section level2">
<h2>核心概念</h2>
<ul>
<li>布局（The Layouts）：定义节点的位置，本质上给出了每个节点在图上的 <code>x</code>，<code>y</code> 坐标。<code>ggraph</code> 在 <code>igraph</code> 原有的布局函数上，又添加了一些（如 hive plots，treemaps 和 circle packing）。</li>
<li>节点（The Nodes）：图上的节点。使用 <code>geom_node_*()</code> 函数家族可视化。一些 geoms 适用于特定 <code>布局</code>（如 <code>geom_node_tile()</code> 适用于 treemaps 和 icicle 图形），而另外一些则具有普适性（如 <code>geom_node_point()</code>。</li>
<li>边（The Edges）：是节点之间的连线。使用 <code>geom_edge_*()</code> 函数家族可视化，不同的场景下会有不同的边的类型。</li>
</ul>
<div id="layouts" class="section level3">
<h3>Layouts</h3>
<p><em>Source: <code>vignettes/Layouts.Rmd</code></em></p>
<p>布局的本质是坐标系中的位置。布局函数所做的事情就是接受一个图的数据结构的输入，计算后输出 <code>xy</code> 坐标。</p>
<p>默认情况下，会调用 <code>auto</code> 布局。</p>
<pre class="r"><code>set_graph_style(plot_margin = margin(1,1,1,1))
graph &lt;- as_tbl_graph(highschool)

# Not specifying the layout - defaults to &quot;auto&quot;
ggraph(graph) + 
  geom_edge_link(aes(colour = factor(year))) + 
  geom_node_point()</code></pre>
<pre><code>## Using `stress` as default layout</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-6-1.png" width="672" /></p>
<p>在 <code>ggraph()</code> 指定布局的同时还可以添加参数。</p>
<pre class="r"><code>ggraph(graph, layout = &#39;kk&#39;, maxiter = 100) + 
  geom_edge_link(aes(colour = factor(year))) + 
  geom_node_point()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-7-1.png" width="672" /></p>
<p><code>ggraph()</code> 也可以使用预先计算好的布局。这在自定义布局的时候很有用。</p>
<pre class="r"><code>layout &lt;- create_layout(graph, layout = &#39;eigen&#39;)</code></pre>
<pre><code>## Warning in layout_with_eigen(graph, type = type, ev = eigenvector): g is
## directed. undirected version is used for the layout.</code></pre>
<pre class="r"><code>ggraph(layout) + 
  geom_edge_link(aes(colour = factor(year))) + 
  geom_node_point()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-8-1.png" width="672" /></p>
<p><code>creat_layout()</code> 的结果是一个数据框，包括 node 的位置和属性。当然，图的其它信息也包含在其中。</p>
<pre class="r"><code>head(layout)</code></pre>
<pre><code>##             x           y circular name .ggraph.orig_index .ggraph.index
## 1 -0.04317633 -0.15611549    FALSE    1                  1             1
## 2 -0.03414457 -0.20843892    FALSE    2                  2             2
## 3 -0.04963286 -0.30081095    FALSE    3                  3             3
## 4  0.18211675  0.03597610    FALSE    4                  4             4
## 5  0.18048193 -0.01111635    FALSE    5                  5             5
## 6  0.01389960 -0.19521616    FALSE    6                  6             6</code></pre>
<pre class="r"><code>attributes(layout)</code></pre>
<pre><code>## $names
## [1] &quot;x&quot;                  &quot;y&quot;                  &quot;circular&quot;          
## [4] &quot;name&quot;               &quot;.ggraph.orig_index&quot; &quot;.ggraph.index&quot;     
## 
## $row.names
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
## [26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
## [51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
## 
## $class
## [1] &quot;layout_tbl_graph&quot; &quot;layout_ggraph&quot;    &quot;data.frame&quot;      
## 
## $graph
## # A tbl_graph: 70 nodes and 506 edges
## #
## # A directed multigraph with 1 component
## #
## # Node Data: 70 x 2 (active)
##   name  .ggraph.orig_index
##   &lt;chr&gt;              &lt;int&gt;
## 1 1                      1
## 2 2                      2
## 3 3                      3
## 4 4                      4
## 5 5                      5
## 6 6                      6
## # ... with 64 more rows
## #
## # Edge Data: 506 x 3
##    from    to  year
##   &lt;int&gt; &lt;int&gt; &lt;dbl&gt;
## 1     1    13  1957
## 2     1    14  1957
## 3     1    20  1957
## # ... with 503 more rows
## 
## $circular
## [1] FALSE</code></pre>
<p>这样的一个 数据框 是可以使用常规的 <code>ggplot2</code> 函数来可视化的，不过，还是建议使用 <code>geom_node_*()</code> 系列来操作比较好。</p>
<p>任何数据，只有能够转变为 <code>tbl_graph</code> 对象就可以使用 <code>ggraph</code> 可视化。</p>
<div id="几个有意思的图形" class="section level4">
<h4>几个有意思的图形</h4>
<div id="分区表" class="section level5">
<h5>分区表</h5>
<pre class="r"><code>graph &lt;- tbl_graph(flare$vertices, flare$edges)
# An icicle plot
ggraph(graph, &#39;partition&#39;) + 
  geom_node_tile(aes(fill = depth), size = 0.25) +
  geom_node_text(aes(label=shortName))</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call.graphics(C_text, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-10-1.png" width="672" /></p>
</div>
<div id="sunburst-plot" class="section level5">
<h5>Sunburst plot</h5>
<pre class="r"><code># A sunburst plot
ggraph(graph, &#39;partition&#39;, circular = TRUE) + 
  geom_node_arc_bar(aes(fill = depth), size = 0.25) + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-11-1.png" width="672" /></p>
</div>
<div id="hive-plot" class="section level5">
<h5>Hive plot</h5>
<pre class="r"><code>graph &lt;- as_tbl_graph(highschool) %&gt;% 
  mutate(degree = centrality_degree())

graph &lt;- graph %&gt;% 
  mutate(friends = ifelse(
    centrality_degree(mode = &#39;in&#39;) &lt; 5, &#39;few&#39;,
    ifelse(centrality_degree(mode = &#39;in&#39;) &gt;= 15, &#39;many&#39;, &#39;medium&#39;)
  ))
ggraph(graph, &#39;hive&#39;, axis = friends, sort.by = degree) + 
  geom_edge_hive(aes(colour = factor(year))) + 
  geom_axis_hive(aes(colour = friends), size = 2, label = FALSE) + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-12-1.png" width="672" /></p>
</div>
<div id="hierarchical-layouts-分层布局" class="section level5">
<h5>Hierarchical layouts 分层布局</h5>
<p>** 关于 flare 数据 **</p>
<blockquote>
<p>This dataset contains the graph that describes the class hierarchy for the Flare ActionScript visualization library. It contains both the class hierarchy as well as the import connections between classes. This dataset has been used extensively in the D3.js documentation and examples and are included here to make it easy to redo the examples in ggraph.</p>
</blockquote>
<pre class="r"><code>graph &lt;- tbl_graph(flare$vertices, flare$edges)
set.seed(1)
ggraph(graph, &#39;circlepack&#39;, weight = size) + 
  geom_node_circle(aes(fill = depth), size = 0.25, n = 50) + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-13-1.png" width="672" /></p>
<pre class="r"><code>set.seed(1)
ggraph(graph, &#39;circlepack&#39;, weight = size) + 
  geom_edge_link() + 
  geom_node_point(aes(colour = depth)) +
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-14-1.png" width="672" /></p>
<pre class="r"><code>ggraph(graph, &#39;tree&#39;) + 
  geom_edge_diagonal()</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-15-1.png" width="672" /></p>
</div>
<div id="matrix-layouts-矩阵布局" class="section level5">
<h5>Matrix Layouts 矩阵布局</h5>
<p>矩阵布局可以最大程度上减少边的遮盖。</p>
<pre class="r"><code>graph &lt;- create_notable(&#39;zachary&#39;)
ggraph(graph, &#39;matrix&#39;, sort.by = node_rank_leafsort()) + 
  geom_edge_point(mirror = TRUE) + 
  coord_fixed()</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-16-1.png" width="672" /></p>
</div>
</div>
</div>
<div id="nodes-节点" class="section level3">
<h3>Nodes 节点</h3>
<p><em>Source：<code>vignettes/Nodes.Rmd</code></em></p>
<p>节点不见得一定是点，也可以是片。</p>
<pre class="r"><code>gr &lt;- tbl_graph(flare$vertices, flare$edges)

ggraph(gr, layout = &#39;partition&#39;) + 
  geom_node_tile(aes(y = -y, fill = depth))</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-17-1.png" width="672" /></p>
<p>通过对数据进行变换，可以控制上面的图 <strong>Y 数值取负数</strong>，以及下面的图 <strong>只显示叶片</strong>。</p>
<pre class="r"><code>ggraph(gr, layout = &#39;dendrogram&#39;, circular = TRUE) + 
  geom_edge_diagonal() + 
  geom_node_point(aes(filter = leaf)) + 
  coord_fixed()</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-18-1.png" width="672" /></p>
<p>最常用的节点 geoms 是 <code>geom_node_point()</code>, <code>geom_node_text()</code> 和 <code>geom_node_label()</code>。</p>
<p><code>geom_node_text()</code> 和 <code>geom_node_label()</code> 从 <code>ggrepel</code> 包中取得了 <code>repel</code> 参数，当设为 <code>True</code> 的时候，可以避免文字遮盖。</p>
<p>此外，<code>geom_node_voronio()</code> 也提供了一种避免遮盖的方案。</p>
<pre class="r"><code>graph &lt;- create_notable(&#39;meredith&#39;) %&gt;% 
  mutate(group = sample(c(&#39;A&#39;, &#39;B&#39;), n(), TRUE))

ggraph(graph, &#39;stress&#39;) + 
  geom_node_voronoi(aes(fill = group), max.radius = 1) + 
  geom_node_point() + 
  geom_edge_link() + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-19-1.png" width="672" /></p>
<p>还有一些其它的酷图。</p>
<pre class="r"><code>l &lt;- ggraph(gr, layout = &#39;partition&#39;, circular = TRUE)

## 分区表图
l + geom_node_arc_bar(aes(fill = depth)) + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-20-1.png" width="672" /></p>
<pre class="r"><code>## 
l + geom_edge_diagonal() + 
  geom_node_point(aes(colour = depth)) + 
  coord_fixed()</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-20-2.png" width="672" /></p>
</div>
<div id="edges" class="section level3">
<h3>Edges</h3>
<p>用作者的话说，“边不仅仅是两个点之间的一条线段”。<code>ggraph</code> 提供了系列函数来进行边的可视化。</p>
<p>首先，准备一下示例数据。</p>
<pre class="r"><code>library(ggraph)
library(tidygraph)
library(purrr)
library(rlang)</code></pre>
<pre><code>## 
## 载入程辑包：&#39;rlang&#39;</code></pre>
<pre><code>## The following objects are masked from &#39;package:purrr&#39;:
## 
##     %@%, as_function, flatten, flatten_chr, flatten_dbl, flatten_int,
##     flatten_lgl, flatten_raw, invoke, list_along, modify, prepend,
##     splice</code></pre>
<pre class="r"><code>set_graph_style(plot_margin = margin(1,1,1,1))
hierarchy &lt;- as_tbl_graph(hclust(dist(iris[, 1:4]))) %&gt;% 
  mutate(Class = map_bfs_back_chr(node_is_root(), .f = function(node, path, ...) {
    if (leaf[node]) {
      as.character(iris$Species[as.integer(label[node])])
    } else {
      species &lt;- unique(unlist(path$result))
      if (length(species) == 1) {
        species
      } else {
        NA_character_
      }
    }
  }))

hairball &lt;- as_tbl_graph(highschool) %&gt;% 
  mutate(
    year_pop = map_local(mode = &#39;in&#39;, .f = function(neighborhood, ...) {
      neighborhood %E&gt;% pull(year) %&gt;% table() %&gt;% sort(decreasing = TRUE)
    }),
    pop_devel = map_chr(year_pop, function(pop) {
      if (length(pop) == 0 || length(unique(pop)) == 1) return(&#39;unchanged&#39;)
      switch(names(pop)[which.max(pop)],
             &#39;1957&#39; = &#39;decreased&#39;,
             &#39;1958&#39; = &#39;increased&#39;)
    }),
    popularity = map_dbl(year_pop, ~ .[1]) %|% 0
  ) %&gt;% 
  activate(edges) %&gt;% 
  mutate(year = as.character(year))</code></pre>
<div id="常规类型" class="section level4">
<h4>常规类型</h4>
<pre class="r"><code>## 纺锤体
ggraph(hairball, layout = &#39;stress&#39;) + 
  geom_edge_fan(aes(colour = year))</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-22-1.png" width="672" /></p>
<pre class="r"><code>## 平行宇宙
# let&#39;s make some of the student love themselves
loopy_hairball &lt;- hairball %&gt;% 
  bind_edges(tibble::tibble(from = 1:5, to = 1:5, year = rep(&#39;1957&#39;, 5)))
ggraph(loopy_hairball, layout = &#39;stress&#39;) + 
  geom_edge_link(aes(colour = year), alpha = 0.25) + 
  geom_edge_loop(aes(colour = year))</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-22-2.png" width="672" /></p>
<pre class="r"><code>## 密度图
ggraph(hairball, layout = &#39;stress&#39;) + 
  geom_edge_density(aes(fill = year)) + 
  geom_edge_link(alpha = 0.25)</code></pre>
<pre><code>## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列

## Warning in grid.Call(C_textBounds, as.graphicsAnnot(x$label), x$x, x$y, :
## Windows字体数据库里没有这样的字体系列</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-22-3.png" width="672" /></p>
<p>关于上面的密度图，可以显示边类型的密度。在上面的图中，如果 1957 年的居多，则显示为偏红色；如果 1958 年的居多，则显示为偏蓝色。</p>
</div>
<div id="斜纹和对角线" class="section level4">
<h4>斜纹和对角线</h4>
<pre class="r"><code>## Diagonals
ggraph(hierarchy, layout = &#39;dendrogram&#39;, height = height) + 
  geom_edge_diagonal()</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-23-1.png" width="672" /></p>
<pre class="r"><code>## Bends
ggraph(hierarchy, layout = &#39;dendrogram&#39;, height = height) + 
  geom_edge_bend()</code></pre>
<p><img src="/post/2019-12-04-ggraph-manual_files/figure-html/unnamed-chunk-23-2.png" width="672" /></p>
</div>
<div id="设定边的细节" class="section level4">
<h4>设定边的细节</h4>
<ul>
<li>使用箭头。</li>
<li>使用贝塞尔曲线</li>
<li>使用标签文字</li>
</ul>
</div>
<div id="connections" class="section level4">
<h4>Connections</h4>
<p>Connections 不是边，但可以用来把 节点 连起来。</p>
</div>
</div>
</div>
<div id="支持的数据类型" class="section level2">
<h2>支持的数据类型</h2>
<p>要生成一个图，需要的关系型数据在 R 中有很多形式。<code>ggraph</code> 是在 <code>tidygraph</code> 包的基础上开发的，后者大部分数据结构在 <code>ggraph</code> 中都是原生支持的。对于新的数据类型，要想获得 <code>ggraph</code> 的支持，只需要扩展支持一个 <code>as_tbl_graph</code> 方法即可。</p>
</div>
<div id="相关包" class="section level2">
<h2>相关包</h2>
<ul>
<li><code>ggdendro</code>: support <code>dendrogram</code> &amp; <code>hclust</code></li>
<li><code>ggtree</code>: support tree-ralated</li>
<li><code>ggnetwork</code>:</li>
<li><code>geomnet</code>:</li>
<li><code>GGally</code>:</li>
</ul>
</div>
<div id="函数速查" class="section level2">
<h2>函数速查</h2>
<p>详见：<a href="https://ggraph.data-imaginist.com/reference/index.html">Reference</a></p>
<div id="plot-construction" class="section level3">
<h3>Plot Construction</h3>
<ul>
<li><code>ggraph()</code> <code>create_layout()</code></li>
</ul>
</div>
<div id="layouts-1" class="section level3">
<h3>Layouts</h3>
<p>布局在 <code>ggraph()</code> 中指定，或者通过 <code>creat_layout()</code> 计算。</p>
<ul>
<li><code>layout_tbl_graph_auto()</code></li>
<li><code>layout_tbl_graph_stress()</code></li>
<li><code>layout_tbl_graph_backbone()</code></li>
<li><code>layout_tbl_graph_*()</code>, Others.</li>
</ul>
</div>
<div id="nodes" class="section level3">
<h3>Nodes</h3>
<ul>
<li><p><code>geom_node_point()</code></p>
<p>Show nodes as points</p></li>
<li><p><code>geom_node_text()</code> <code>geom_node_label()</code></p>
<p>Annotate nodes with text</p></li>
<li><p><code>geom_node_tile()</code></p>
<p>Draw the rectangles in a treemap</p></li>
<li><p><code>geom_node_voronoi()</code></p>
<p>Show nodes as voronoi tiles</p></li>
<li><p><code>geom_node_circle()</code></p>
<p>Show nodes as circles</p></li>
<li><p><code>geom_node_arc_bar()</code></p>
<p>Show nodes as thick arcs</p></li>
<li><p><code>geom_node_range()</code></p>
<p>Show nodes as a line spanning a horizontal range</p></li>
</ul>
</div>
<div id="edges-1" class="section level3">
<h3>Edges</h3>
<ul>
<li><p><code>geom_edge_link()</code> <code>geom_edge_link2()</code> <code>geom_edge_link0()</code></p>
<p>Draw edges as straight lines between nodes</p></li>
<li><p><code>geom_edge_arc()</code> <code>geom_edge_arc2()</code> <code>geom_edge_arc0()</code></p>
<p>Draw edges as Arcs</p></li>
<li><p><code>geom_edge_parallel()</code> <code>geom_edge_parallel2()</code> <code>geom_edge_parallel0()</code></p>
<p>Draw multi edges as parallel lines</p></li>
<li><p><code>geom_edge_fan()</code> <code>geom_edge_fan2()</code> <code>geom_edge_fan0()</code></p>
<p>Draw edges as curves of different curvature</p></li>
<li><p><code>geom_edge_loop()</code> <code>geom_edge_loop0()</code></p>
<p>Draw edges as diagonals</p></li>
<li><p><code>geom_edge_diagonal()</code> <code>geom_edge_diagonal2()</code> <code>geom_edge_diagonal0()</code></p>
<p>Draw edges as diagonals</p></li>
<li><p><code>geom_edge_elbow()</code> <code>geom_edge_elbow2()</code> <code>geom_edge_elbow0()</code></p>
<p>Draw edges as elbows</p></li>
<li><p><code>geom_edge_bend()</code> <code>geom_edge_bend2()</code> <code>geom_edge_bend0()</code></p>
<p>Draw edges as diagonals</p></li>
<li><p><code>geom_edge_hive()</code> <code>geom_edge_hive2()</code> <code>geom_edge_hive0()</code></p>
<p>Draw edges in hive plots</p></li>
<li><p><code>geom_edge_span()</code> <code>geom_edge_span2()</code> <code>geom_edge_span0()</code></p>
<p>Draw edges as vertical spans</p></li>
<li><p><code>geom_edge_point()</code></p>
<p>Draw edges as glyphs</p></li>
<li><p><code>geom_edge_tile()</code></p>
<p>Draw edges as glyphs</p></li>
<li><p><code>geom_edge_density()</code></p>
<p>Show edges as a density map</p></li>
</ul>
</div>
<div id="connections-1" class="section level3">
<h3>Connections</h3>
<p>Connections are meta-edges, connecting nodes that are not direct neighbors, either through their shortest path or directly.</p>
<ul>
<li><p><code>geom_conn_bundle()</code> <code>geom_conn_bundle2()</code> <code>geom_conn_bundle0()</code></p>
<p>Create hierarchical edge bundles between node connections</p></li>
</ul>
</div>
<div id="facets" class="section level3">
<h3>Facets</h3>
<p>Faceting with networks is a bit different than for tabular data, as you’d often want to facet only nodes, or edges etc.</p>
<ul>
<li><p><code>facet_graph()</code></p>
<p>Create a grid of small multiples by node and/or edge attributes</p></li>
<li><p><code>facet_nodes()</code></p>
<p>Create small multiples based on node attributes</p></li>
<li><p><code>facet_edges()</code></p>
<p>Create small multiples based on edge attributes</p></li>
</ul>
</div>
<div id="scales" class="section level3">
<h3>Scales</h3>
<p>While nodes uses the standard scales provided by ggplot2, edges have their own, allowing you to have different scaling for nodes and edges.</p>
<ul>
<li><code>scale_edge_colour_*()</code>: Edge color</li>
<li><code>scale_edge_fill_*()</code>: Edge fill</li>
<li><code>scale_edge_alpha*()</code>: Edge alpha</li>
<li><code>scale_edge_width_*()</code>: Edge width</li>
<li><code>scale_edge_size_*()</code>: Edge size</li>
<li><code>scale_edge_lintype*()</code>:</li>
<li><code>scale_edge_shape*()</code></li>
<li><code>scale_label_size*()</code>: Edge label size</li>
</ul>
</div>
</div>
